//
//  YBWIAPManager.m
//  AFNetworking
//
//  Created by ZXJ on 2018/12/24.
//

#import "YBWIAPManager.h"
#import <StoreKit/StoreKit.h>
#import "YBWNetHTTPClient.h"
#import "YBWBaseMeditor+YBWAccountModule.h"
#import "YBWDateOperation.h"
#import "MBProgressHUD.h"
#import "YBWToast.h"
#import "NSString+YBWString.h"


@interface YBWIAPManager ()<SKProductsRequestDelegate,SKPaymentTransactionObserver>{
    
}

@property (nonatomic, copy) NSString * selectProductID;

@property (nonatomic, copy) NSString * orderCode;

/**
 sandbox ：0 表示sandbox测试 ，1 表示正是环境
 */
@property (nonatomic, assign) NSInteger sandbox;

@property (nonatomic, copy) YBWIAPCompletionBolck  completion;


@property (nonatomic, copy) YBWIAPCompletionBolck  cheakCompletionBlock;

@property(nonatomic, copy) NSString * transactionIdentifier;

@end

@implementation YBWIAPManager


static YBWIAPManager * _manager;

+ (instancetype)shareIAPManager{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        _manager = [[YBWIAPManager alloc] init];
        
    });
    
    return _manager;
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    }
    return self;
}

- (void)dealloc
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    
}

#pragma mark - Start pay
- (void)startPurchWithProductID:(nonnull NSString *)productID orderCode:(nonnull NSString *)orderCode completion:(nonnull YBWIAPCompletionBolck)completion{
    
    if (productID.length == 0) {
        
        NSLog(@"产品id不能为空 ！");
        
        return;
    }
    
    if ([SKPaymentQueue canMakePayments]) {
        
        self.selectProductID = productID;
        self.orderCode = orderCode;
        self.completion = completion;
        [self requestProductWithProductID:_selectProductID];
        
    }else{
        
        [self showIAPAlertView];
        [self handleCompletion:NO message:@"没有内购权限"];
        
    }
    
}

- (void)showIAPAlertView{
    
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"请先开启应用内付费购买功能" preferredStyle:UIAlertControllerStyleAlert];
    //    UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    //
    //    }];
    UIAlertAction * enterAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        
    }];
    //    [alertController addAction:cancelAction];
    [alertController addAction:enterAction];
    [[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alertController animated:YES completion:^{}];
    
}

- (void)requestProductWithProductID:(NSString *)productID{
    
    // 1.拿到所有可卖商品的ID数组
    NSArray *productIDArray = [[NSArray alloc]initWithObjects:productID, nil];
    NSSet *sets = [[NSSet alloc]initWithArray:productIDArray];
    
    // 2.向苹果发送请求，请求所有可买的商品
    SKProductsRequest *sKProductsRequest = [[SKProductsRequest alloc]initWithProductIdentifiers:sets];
    sKProductsRequest.delegate = self;
    [sKProductsRequest start];
    
}

#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    //    NSLog(@"可卖商品的数量=%ld",response.products.count);
    
    NSArray *product = response.products;
    if([product count] <= 0){
        
        NSLog(@"没有商品");
        return;
    }
    
    for (SKProduct *sKProduct in product) {
        
        //        NSLog(@"pro info");
        //        NSLog(@"SKProduct 描述信息：%@", sKProduct.description);
        //        NSLog(@"localizedTitle 产品标题：%@", sKProduct.localizedTitle);
        //        NSLog(@"localizedDescription 产品描述信息：%@",sKProduct.localizedDescription);
        //        NSLog(@"price 价格：%@",sKProduct.price);
        //        NSLog(@"productIdentifier Product id：%@",sKProduct.productIdentifier);
        
        if([sKProduct.productIdentifier isEqualToString: _selectProductID]){
            
            [self buyProduct:sKProduct];
            
            break;
            
        }else{
            
            NSLog(@"不是我们的产品！！！");
        }
    }
    
}

#pragma mark - SKPaymentTransactionObserver

/**
 支付状态监听
 
 SKPaymentTransactionStatePurchasing,    正在购买
 SKPaymentTransactionStatePurchased,     已经购买
 SKPaymentTransactionStateFailed,        购买失败
 SKPaymentTransactionStateRestored,      回复购买中
 SKPaymentTransactionStateDeferred       交易还在队列里面，但最终状态还没有决定
 
 @param queue 交易队列
 @param transactions 交易
 */
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing:{
                NSLog(@"正在购买…");
            }break;
            case SKPaymentTransactionStatePurchased:{
                
                NSLog(@"购买成功");
                [queue finishTransaction:transaction]; // 购买后告诉交易队列，把这个成功的交易移除掉
                [self buyAppleStoreProductSucceedWithPaymentTransactionp:transaction];
                
            }break;
            case SKPaymentTransactionStateFailed:{
                
                NSLog(@"购买失败");
                [self handleCompletion:NO message:@"购买失败"];
                [queue finishTransaction:transaction];// 购买失败也要把这个交易移除掉
                
                
            }break;
            case SKPaymentTransactionStateRestored:{
                NSLog(@"回复购买中,也叫做已经购买");
                [queue finishTransaction:transaction];// 回复购买中也要把这个交易移除掉
                
                
            }break;
            case SKPaymentTransactionStateDeferred:{
                
                NSLog(@"交易还在队列里面，但最终状态还没有决定");
                
            }break;
            default:
                break;
        }
    }
    
}

#pragma mark - Private

/**
 向AppStroe发起支付
 
 @param product 票据
 */
- (void)buyProduct:(SKProduct *)product{
    
    SKPayment *skpayment = [SKPayment paymentWithProduct:product]; // 1.创建票据
    [[SKPaymentQueue defaultQueue] addPayment:skpayment];// 2.将票据加入到交易队列
    
}

/**
 苹果内购支付成功， 验证凭据，获取到苹果返回的交易凭据验证
 
 @param paymentTransaction 交易
 */
- (void)buyAppleStoreProductSucceedWithPaymentTransactionp:(SKPaymentTransaction *)paymentTransaction {
    
    NSURLRequest * appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle] appStoreReceiptURL]];//购买交易完成后，会将凭据存放在该地址
    NSError *error = nil;
    NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:&error];
    
    if (receiptData) {
        
        self.transactionIdentifier = paymentTransaction.transactionIdentifier;
        NSString *transactionReceiptString = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
        [self checkIAPEnvironmentWithBase64ReceiptString:transactionReceiptString];
        
    }else{
        
        [self handleCompletion:NO message:@"支付失败"];
    }
}

/**
 去我们的服务器验证是否真正的支付成功了，生成订单参数，注意沙盒测试账号与线上正式苹果账号的验证途径不一样，要给后台标明
 
 苹果AppStore线上的购买凭证地址是： https://buy.itunes.apple.com/verifyReceipt
 测试地址是：https://sandbox.itunes.apple.com/verifyReceipt
 
 @param base64String 交易凭证
 */
- (void)checkAppStorePayResultWithBase64String:(NSString *)base64String {
    
    //    NSLog(@"IAP凭证：%@",base64String);
    [self verifyReceiptForIOSRequestWithReceiptCode:base64String env:self.sandbox orderCode:_orderCode];
    
}

- (void)checkYBWServerePayResultOrderCode:(NSString *)orderCode completion:(nonnull YBWIAPCompletionBolck)completion{
    
    self.cheakCompletionBlock = completion;
    self.orderCode = orderCode;
    [self checkIAPEnvironmentWithOrderCode:orderCode];
}

#pragma mark - Check is sandbox

/**
 获得验证环境
 
 21000 App Store无法读取你提供的JSON数据
 21002 收据数据不符合格式
 21003 收据无法被验证
 21004 你提供的共享密钥和账户的共享密钥不一致
 21005 收据服务器当前不可用
 21006 收据是有效的，但订阅服务已经过期。当收到这个信息时，解码后的收据信息也包含在返回内容中
 21007 收据信息是测试用（sandbox），但却被发送到产品环境中验证
 21008 收据信息是产品环境中使用，但却被发送到测试环境中验证
 
 */
- (void)checkIAPEnvironmentWithOrderCode:(NSString*)orderCode{
    
    //购买交易完成后，会将凭据存放在该地址
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
    /**
     BASE64 常用的编码方案，通常用于数据传输，以及加密算法的基础算法，传输过程中能够保证数据传输的稳定性
     BASE64是可以编码和解码的
     */
    
    if (receiptData) {
        
        NSDictionary *requestContents = @{ @"receipt-data": [receiptData base64EncodedStringWithOptions:0] };
        NSError *error;
        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                              options:0
                                                                error:&error];
        
        NSString *verifyUrlString = @"https://buy.itunes.apple.com/verifyReceipt";
        
        NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[[NSURL alloc] initWithString:verifyUrlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
        
        [storeRequest setHTTPMethod:@"POST"];
        [storeRequest setHTTPBody:requestData];
        
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                                   if (connectionError) {
                                       NSLog(@"链接失败");
                                       
                                       [self handleCheckCompletionBlock:NO message:@"网络异常"];
                                       [MBProgressHUD hideHUDForView:[[[UIApplication sharedApplication] delegate] window] animated:YES];
                                       
                                       
                                   } else {
                                       NSError *error;
                                       NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                       
                                       if (error) {
                                           
                                           [self handleCompletion:NO message:@"支付失败"];
                                           [MBProgressHUD hideHUDForView:[[[UIApplication sharedApplication] delegate] window] animated:YES];
                                           
                                       } else{
                                           
                                           NSInteger status = [jsonResponse[@"status"] integerValue];
                                           
                                           if (status == 21007) {//收据信息是产品环境中使用，但却被发送到测试环境中验证
                                               self.sandbox = 0;
                                           }else{
                                               self.sandbox = 1;
                                           }
                                           
                                           if (orderCode) {
                                               
                                               [self verifyReceiptForIOSRequestWithorderCode:orderCode env:self.sandbox];
                                               
                                           }else{
                                               
                                               [self scanIAPReceipt];
                                               
                                           }
                                       }
                                   }
                               }];
        
    }
    
}


/**
 根据支付凭证，获得验证环境
 
 @param receiptString 支付凭证
 */
- (void)checkIAPEnvironmentWithBase64ReceiptString:(NSString *)receiptString{
    
    NSDictionary *requestContents = @{ @"receipt-data": receiptString };
    NSError *error;
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];
    
    NSString *verifyUrlString = @"https://buy.itunes.apple.com/verifyReceipt";
    
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[[NSURL alloc] initWithString:verifyUrlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
    
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               if (connectionError) {
                                   
                                   [self handleCompletion:NO message:@"网络异常"];
                                   
                               } else {
                                   NSError *error;
                                   NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                   
                                   if (error) {
                                       
                                       [self handleCompletion:NO message:@"支付失败"];
                                       
                                   } else{
                                       
                                       NSInteger status = [jsonResponse[@"status"] integerValue];
                                       
                                       if (status == 21007) {//收据信息是产品环境中使用，但却被发送到测试环境中验证
                                           
                                           self.sandbox = 0;
                                       }else{
                                           self.sandbox = 1;
                                       }
                                       
                                       [self verifyReceiptForIOSRequestWithReceiptCode:receiptString env:self.sandbox orderCode:_orderCode];
                                       
                                       
                                   }
                               }
                           }];
    
    
}

#pragma mark - Verify receipt request
/**
 IAP服务器验证
 
 @param receiptCode 支付凭证
 @param env 验证环境
 */
- (void)verifyReceiptForIOSRequestWithorderCode:(NSString *)orderCode env:(NSInteger)env{
    
    if (orderCode.length == 0) {
        
        return ;
    }
    
    NSString * url = @"/pay/thirdParty/verifyReceiptForIOS";
    NSDictionary * param = @{@"env":[NSNumber numberWithInteger:env],@"orderCode":orderCode};
    
    [YBWNetHTTPClient ybw_postJSONRequestUrl:url parameters:param onSuccess:^(id  _Nullable responseObject) {
        
        NSInteger code = [responseObject[@"code"] integerValue];
        NSString * message = responseObject[@"message"];
        if (code == 0) {
            
            [self handleCheckCompletionBlock:YES message:message];
            [self removeIAPReceiptWithOrderCode:orderCode];//根据orderCode，删除本地缓存的支付凭证
            
        }else{
            
            [self handleCheckCompletionBlock:NO message:message];
            [self showVerifyFailedAlert];
            
        }
        
    } onFailure:^(NSError *error) {
        
        [self handleCheckCompletionBlock:NO message:@"网络异常"];
        
    }];
}
/**
 IAP服务器验证
 
 @param receiptCode 支付凭证
 @param env 验证环境
 */
- (void)verifyReceiptForIOSRequestWithReceiptCode:(NSString *)receiptCode env:(NSInteger)env orderCode:(NSString * )orderCode{
    
    if (orderCode.length == 0) {
        
        return ;
    }
    
    NSString * url = @"/pay/thirdParty/verifyReceiptForIOS";
    NSDictionary * param = @{@"env":[NSNumber numberWithInteger:env],@"receiptCode":receiptCode ? receiptCode : @"",@"orderCode":_orderCode,@"transactionId":_transactionIdentifier ? : @""};
    
    [YBWNetHTTPClient ybw_postJSONRequestUrl:url parameters:param onSuccess:^(id  _Nullable responseObject) {
        
        NSInteger code = [responseObject[@"code"] integerValue];
        NSString * message = responseObject[@"message"];
        if (code == 0) {
            
            [self handleCompletion:YES message:message];
            
        }else{
            
            [self saveIAPReceiptWithreceiptCode:receiptCode orderCode:orderCode productID:_selectProductID transactionIdentifier:_transactionIdentifier];
            [self handleCompletion:NO message:message];
            [self showVerifyFailedAlert];
            
        }
        
    } onFailure:^(NSError *error) {
        
        [self handleCompletion:NO message:@"网络异常"];
        [self saveIAPReceiptWithreceiptCode:receiptCode orderCode:orderCode productID:_selectProductID transactionIdentifier:_transactionIdentifier];
        
    }];
}

/**
 同步服务器，验证支付凭证
 
 @param filePath 凭证保存的路径
 */
- (void)verifyReceiptForIOSRequestWithFilePath:(NSString *)fileName{
    
    NSString * receiptPath = [NSString stringWithFormat:@"%@/%@/", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],@"YBWIAPReceipt"];
    
    NSString * filePath = [NSString stringWithFormat:@"%@/%@",receiptPath,fileName];
    
    NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
    NSString * transactionIdentifier = dict[@"transactionId"];
    NSString * receiptCode = dict[@"receiptCode"];
    NSString * orderCode = dict[@"orderCode"];
    NSString * userId = dict[@"userId"];
    
    if (![userId isEqualToString:[[YBWBaseMeditor sharedInstance] userId]]) {//不是当前用户的recept，不验证
     
        return;
    }
    
    if (receiptCode.length == 0 || orderCode.length == 0) {
        
        return ;
    }
    
    NSString * url = @"/pay/thirdParty/verifyReceiptForIOS";
    NSDictionary * param = @{@"env":[NSNumber numberWithInteger:self.sandbox],@"receiptCode":receiptCode,@"orderCode":orderCode,@"transactionId":transactionIdentifier?:@""};
    
    [YBWNetHTTPClient ybw_postJSONRequestUrl:url parameters:param onSuccess:^(id  _Nullable responseObject) {
        
        NSInteger code = [responseObject[@"code"] integerValue];
        NSString * message = responseObject[@"message"];
        
        if (code == 0) {
            
            [self removeIAPReceiptWithFilePath:filePath];
            [YBWToast showWithErrorMsg:@"支付验证成功"];
            [self handleCompletion:YES message:@"支付验证成功"];
            
        }else{
            [YBWToast showWithErrorMsg:@"支付验证失败"];
            [self handleCompletion:NO message:@"支付验证失败"];
            
        }
        [MBProgressHUD hideHUDForView:[[[UIApplication sharedApplication] delegate] window] animated:YES];
        
    } onFailure:^(NSError *error) {
        [MBProgressHUD hideHUDForView:[[[UIApplication sharedApplication] delegate] window] animated:YES];
        [self handleCompletion:NO message:@"网络异常"];
        
        
    }];
    
}

- (void)showVerifyFailedAlert{
    
    UIWindow * window = [[[UIApplication sharedApplication] delegate] window];
    
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"服务器验证支付失败，请重试" preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction * enterAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        [MBProgressHUD showHUDAddedTo:window animated:YES];
        
        [self checkIAPEnvironmentWithOrderCode:nil];
        
    }];
    [alertController addAction:enterAction];
    [[window rootViewController] presentViewController:alertController animated:YES completion:^{}];
    
}

#pragma mark - Handle block

- (void)handleCompletion:(BOOL )success message:(NSString *)message{
    
    if (_completion) {
        _completion(success,message);
    }
}

- (void)handleCheckCompletionBlock:(BOOL )success message:(NSString *)message{
    
    if (_cheakCompletionBlock) {
        _cheakCompletionBlock(success,message);
    }
}
#pragma mark - Receipt cache

/**
 保存支付凭证
 
 @param receiptCode 支付凭证
 @param orderCode 支付订单code
 @param productID 产品id
 */

- (void)saveIAPReceiptWithreceiptCode:(NSString *)receiptCode orderCode:(NSString *)orderCode productID:(NSString *)productID transactionIdentifier:(NSString *)transactionIdentifier{
    
    NSFileManager * fileManger = [NSFileManager defaultManager];
    
    NSString * filePath = [NSString stringWithFormat:@"%@/%@/", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],@"YBWIAPReceipt"];
    //    NSLog(@"Path:%@",filePath);
    
    if (![fileManger fileExistsAtPath:filePath]) {
        [fileManger createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    NSString * plistPath = [NSString stringWithFormat:@"%@.plist",[[NSUUID UUID] UUIDString]];
    NSString * savedPath = [filePath stringByAppendingPathComponent:plistPath];
    
    NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithCapacity:0];
    [dict setValue:receiptCode forKey:@"receiptCode"];
    [dict setValue:orderCode forKey:@"orderCode"];
    [dict setValue:productID forKey:@"productID"];
    [dict setValue:transactionIdentifier forKey:@"transactionIdentifier"];
    [dict setValue:[[YBWBaseMeditor sharedInstance] userId] forKey:@"userId"];
    [dict setValue:[YBWDateOperation ybw_todayWithDateFormat:@"yyyy-MM-dd HH:mm:ss"] forKey:@"date"];
    
    [dict writeToFile:savedPath atomically:YES];
    
}

- (void)checkIAPReceiptIsValid{
    
    [self checkIAPEnvironmentWithOrderCode:nil];
    
}

/**
 扫描支付支付凭证
 */
- (void)scanIAPReceipt{
    
    NSFileManager * fileManager = [NSFileManager defaultManager];
    NSString * filePath = [NSString stringWithFormat:@"%@/%@/", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],@"YBWIAPReceipt"];
    
    NSError * error ;
    
    NSArray * fileArray = [fileManager contentsOfDirectoryAtPath:filePath error:&error];
    
    if (!error) {
        
        for (NSString * fileName in fileArray) {
            
            if ([fileName hasSuffix:@".plist"]) {
                
                [self verifyReceiptForIOSRequestWithFilePath:fileName];
                
            }
            
        }
    }
}


/**
 删除支付凭证
 
 @param filePath 支付凭证路径
 */
- (void)removeIAPReceiptWithFilePath:(NSString *)filePath{
    
    NSFileManager * manager = [NSFileManager defaultManager];
    if ([manager fileExistsAtPath:filePath]) {
        
        [manager removeItemAtPath:filePath error:nil];
        
    }
}

/**
 根据支付orderCode，删除响应的IAP支付凭证
 
 @param orderCode 订单Code
 */
- (void)removeIAPReceiptWithOrderCode:(NSString *)orderCode{
    
    NSFileManager * fileManager = [NSFileManager defaultManager];
    NSString * filePath = [NSString stringWithFormat:@"%@/%@/", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject],@"YBWIAPReceipt"];
    
    NSError * error ;
    
    NSArray * fileArray = [fileManager contentsOfDirectoryAtPath:filePath error:&error];
    
    if (!error) {
        
        for (NSString * fileName in fileArray) {
            
            if ([fileName hasSuffix:@".plist"]) {
                
                NSString * receiptPath = [NSString stringWithFormat:@"%@/%@",filePath,fileName];
                
                NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:receiptPath];
                
                if ([orderCode isEqualToString:dict[@"orderCode"]]) {
                    [self removeIAPReceiptWithFilePath:receiptPath];
                }
                
            }
            
        }
    }
    
}


@end
